/*
testing allegro game library
*/

#include "allegrowrapper.h"

AllegroWrapper* AllegroWrapper::_instance = 0;

AllegroWrapper::AllegroWrapper() {
    fps = 50;
    screen_w = 640;
    screen_h = 480;

    redraw = true;
    done = false;

    firstResponder = 0;
}

AllegroWrapper* AllegroWrapper::Instance() {
	// If we haven't created a controller yet, create it and return it
    // either way.
	if (0 == _instance) {
		_instance = new AllegroWrapper();
	}

	return _instance;
}

MyController* AllegroWrapper::getFirstResponder() {
    return firstResponder;
}
void AllegroWrapper::setFirstResponder(MyController* val) {
    firstResponder = val;
}

bool AllegroWrapper::initAll() {
    bool success = true;

    // initialize Allegro library
    if(!init()) success = false;

    // initialize graphics primitives addon
    if(!initPrimitives()) success = false;

    // initialize event generators
    if(!initKeyboard()) success = false;
    if(!initMouse()) success = false;
    if(!initDisplay()) success = false;
    if(!initTimer()) success = false;

    // initialize event queue
    if(!initQueue()) success = false;

    if(!success) cleanup();

    return success;
}

bool AllegroWrapper::init() {
    // initialize allegro
    return al_init();
}

bool AllegroWrapper::initPrimitives() {
    // initialize graphics primitives addon
    return al_init_primitives_addon();
}

bool AllegroWrapper::initKeyboard() {
    if(!al_install_keyboard()) return false;

    keyboard_source = al_get_keyboard_event_source();
    event_sources.push_back(keyboard_source);

    return true;
}
bool AllegroWrapper::initMouse() {
    if(!al_install_mouse()) return false;

    mouse_source = al_get_mouse_event_source();
    event_sources.push_back(mouse_source);

    return true;
}

int AllegroWrapper::getScreenW() {
    return screen_w;
}
void AllegroWrapper::setScreenW(int val) {
    screen_w = val;
}
int AllegroWrapper::getScreenH() {
    return screen_h;
}
void AllegroWrapper::setScreenH(int val) {
    screen_h = val;
}
bool AllegroWrapper::initDisplay() {
    // set up screen: set width and height
    display = al_create_display(screen_w, screen_h);
    if(!display) return false;

    display_source = al_get_display_event_source(display);
    event_sources.push_back(display_source);

    return true;
}

float AllegroWrapper::getFPS() {
    return fps;
}
void AllegroWrapper::setFPS(float val) {
    fps = val;
}
bool AllegroWrapper::initTimer() {
    double speed_secs = 1.0 / fps;
    timer = al_create_timer(speed_secs);
    timer_source = al_get_timer_event_source(timer);
    event_sources.push_back(timer_source);
    return true;
}

bool AllegroWrapper::initQueue() {
    // create event queue
    queue = al_create_event_queue();
    if(!queue) return false;

    for(int i = 0; i < event_sources.size(); i++) {
        al_register_event_source(queue, event_sources[i]);
    }
    
    return true;
}

void AllegroWrapper::needRedraw() {
    redraw = true;
}
void AllegroWrapper::makeDone() {
    done = true;
}

void AllegroWrapper::cleanup() {
    try {al_destroy_display(display);}
    catch (...) {}
    try {al_destroy_event_queue(queue);}
    catch (...) {}
    try {al_destroy_timer(timer);}
    catch (...) {}
}

void AllegroWrapper::go() {
    al_start_timer(timer);

    while(!done) {
        ALLEGRO_EVENT ev;
        al_wait_for_event(queue, &ev);

        firstResponder->processEvent(&ev);

        if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) done = true;

        // redraw only after event queue has been emptied
        if(redraw && al_is_event_queue_empty(queue)) {
            al_clear_to_color(al_map_rgb(0,0,0));
            view->draw();
            al_flip_display();
            redraw = false;
        }
    }
    cleanup();
}

void AllegroWrapper::processEvent(ALLEGRO_EVENT* ev) {
    switch (ev->type) {
        case ALLEGRO_EVENT_KEY_CHAR:
            // determine action from key
            if(ev->keyboard.keycode == ALLEGRO_KEY_Q) {
                done = true;
            }
        case ALLEGRO_EVENT_DISPLAY_CLOSE:
            done = true;
            break;
        default:
            break;
    }
}

